﻿#if NET45_OR_GREATER
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

using Newtonsoft.Json;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Core;
using zijian666.Core.Abstractions;

namespace zijian666.Converts.Json;

/// <summary>
/// JSON字符串序列化程序
/// </summary>
public class JsonStringSerializer : IStringSerializer
{
    private readonly JsonSerializerSettings _deserializeSettings = new()
    {
        Converters = {
            new JsonElementTranslator(),
            new JsonValueConverter<DateTime>(),
            new JsonValueConverter<TimeSpan>(),
            new JsonValueConverter<DateTimeOffset>(),
            new JsonValueConverter<Guid>()
        }
    };

    private readonly JsonSerializerSettings _serializeSettings = new()
    {
        Converters = { 
            new JsonValueConverter<DateTime>(), 
            new JsonValueConverter<TimeSpan>(), 
            new JsonValueConverter<DateTimeOffset>(), 
            new JsonValueConverter<Guid>(), 
            new ProxyObjectJsonConvererFactory()
        },
    };

    /// <inheritdoc />
    public string ToString(object value)
    {
        if (ConvertContext.Current?.Settings?.StringSerializer is null)
        {
            return JsonConvert.SerializeObject(value, _serializeSettings);
        }
        using var _ = ConvertContext.CreateScope(new JsonConvertSettings(ConvertContext.Current?.Settings));
        return JsonConvert.SerializeObject(value, _serializeSettings);
    }

    /// <inheritdoc />
    public object ToObject(string value, Type? type = null)
    {
        if (ConvertContext.Current?.Settings?.StringSerializer is null)
        {
            return JsonConvert.DeserializeObject(value, type ?? typeof(object), _deserializeSettings);
        }
        using var _ = ConvertContext.CreateScope(new JsonConvertSettings(ConvertContext.Current?.Settings));
        return JsonConvert.DeserializeObject(value, type ?? typeof(object), _deserializeSettings);
    }

    /// <inheritdoc />
    public string Protocol => "json";

    /// <summary>
    /// JSON序列化时替换转换参数，将字符串协议置空，防止递归
    /// </summary>
    private class JsonConvertSettings : IConvertSettings
    {
        private readonly IConvertSettings _settings;

        public JsonConvertSettings(IConvertSettings? settings) => _settings = settings ?? Converts.Settings;

        public IEnumerable<ITranslator>? Translators => _settings.Translators;

        public IStringSerializer? StringSerializer => null;

        public IReflectCompiler? ReflectCompiler => _settings.ReflectCompiler;

        public CultureInfo? CultureInfo => _settings.CultureInfo;

        public NumberFormatInfo? NumberFormatInfo => _settings.NumberFormatInfo;

        public Encoding? Encoding => _settings.Encoding;

        public IConvertor<T>? GetConvertor<T>(IConvertContext context) => _settings.GetConvertor<T>(context);
        public ToStringArgument? GetToStringArgument(Type type) => _settings.GetToStringArgument(type);

        public StringSeparator? StringSeparator => _settings.StringSeparator;

        public bool StrictEnum => _settings.StrictEnum;

        public StringSplitOptions StringSplitOptions => _settings.StringSplitOptions;
    }
}

#endif